package com.zoran.study.spring.util;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.net.SocketTimeoutException;
import java.util.concurrent.TimeUnit;

/**
 * http请求工具类
 *
 * @author zouxm
 */
public final class HttpClientUtil {

    private static Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);
    static PoolingHttpClientConnectionManager manager = null;
    static CloseableHttpClient httpClient = null;

    public static synchronized CloseableHttpClient getHttpClient() {
        if (httpClient == null) {
            /*//注册访问协议Socket工厂
            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register("http", PlainConnectionSocketFactory.INSTANCE)
                    .register("https", SSLConnectionSocketFactory.getSystemSocketFactory())
                    .build();
         /*   //创建池化连接管理器,使用默认配置*//*
            manager = new PoolingHttpClientConnectionManager();
            //设置连接池最大连接数
            manager.setMaxTotal(300);
            //设置每个路由最大连接数
            manager.setDefaultMaxPerRoute(200);*/

            //请求设置
            RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(5 * 1000).
                    setSocketTimeout(10 * 1000)
                    .build();
            httpClient = HttpClients.custom()
                    .setDefaultRequestConfig(requestConfig)
                    .evictIdleConnections(60, TimeUnit.SECONDS)
                    .evictExpiredConnections()
                    //禁用重试策略
                    .setRetryHandler(new DefaultHttpRequestRetryHandler(0, false))
                    .build();

            Runtime.getRuntime().addShutdownHook(new Thread() {
                @Override
                public void run() {
                    try {
                        httpClient.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
        return httpClient;
    }

    /**
     * 通过post方式发送请求
     *
     * @param url  请求的url
     * @param body 请求体
     * @return
     */
    public static String sendPost(String url, String body, ContentType contentType) throws Exception {
        HttpPost request = new HttpPost(url);
        StringEntity entity;
        if (body == null) {
            entity = new StringEntity("", contentType);
        } else {
            entity = new StringEntity(body, contentType);
        }
        request.setEntity(entity);
        HttpResponse response = getHttpClient().execute(request);
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode == HttpStatus.SC_NOT_FOUND) {
            throw new Exception("404,not found.");
        }
        if (statusCode == HttpStatus.SC_REQUEST_TIMEOUT) {
            throw new SocketTimeoutException(EntityUtils.toString(response.getEntity()));
        }
        if (statusCode == HttpStatus.SC_NO_CONTENT) {
            return null;
        }
        if (statusCode != HttpStatus.SC_OK) {
            if (response == null || response.getEntity() == null) {
                throw new Exception(String.format("调用业务接口错误:未获取到正确响应"));
            }
            throw new Exception(String.format("调用业务接口错误:【%s】",
                    EntityUtils.toString(response.getEntity())));
        }
        return EntityUtils.toString(response.getEntity());
    }


    /**
     * 通过GET方式发送请求
     *
     * @param url 请求的url
     * @return
     */
    public static String sendGet(String url) throws Exception {
        HttpGet request = new HttpGet(url);
        HttpResponse response = getHttpClient().execute(request);
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode == HttpStatus.SC_NOT_FOUND) {
            throw new Exception("404,not found.");
        }
        if (statusCode == HttpStatus.SC_REQUEST_TIMEOUT) {
            throw new SocketTimeoutException(EntityUtils.toString(response.getEntity()));
        }
        if (statusCode == HttpStatus.SC_NO_CONTENT) {
            return null;
        }
        if (statusCode != HttpStatus.SC_OK) {
            if (response == null || response.getEntity() == null) {
                throw new Exception(String.format("调用业务接口错误:未获取到正确响应"));
            }
            throw new Exception(String.format("Response:【%s】,ResponseCode:【%s】",
                    EntityUtils.toString(response.getEntity()), statusCode));
        }
        return EntityUtils.toString(response.getEntity());
    }

    /**
     * 通过GET方式发送请求
     *
     * @param url 请求的url
     * @return
     */
    public static String sendGet(String url, String queryString) throws Exception {
        StringBuilder builderUrl = null;
        if (!StringUtils.isEmpty(url)) {

            builderUrl = new StringBuilder(url);
        }
        if (StringUtils.isEmpty(queryString)) {
            builderUrl.append("?").append(queryString);
        }
        return builderUrl == null ? null : sendGet(builderUrl.toString());
    }


}

